﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.IO;
using System.Windows.Interop;
using VideoClipNameHelper;

namespace ClipPlayer
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        //
        VideoClipNameHelper.ConfigPaths cp = new VideoClipNameHelper.ConfigPaths();
        //
        private VideoClipNameHelper.MediaDirectory md = new VideoClipNameHelper.MediaDirectory();
        private int currentPlaying = 0;
        //
        //====================================================================================================================

        public MainWindow()
        {
            InitializeComponent();
            //
            progressBar1.Minimum = 0;
            progressBar1.Maximum = 100;
            //progresBar1.ToolTipText = "";
            //
            //Task.Factory.StartNew(new Action(DbStatistics.CreateDbIfNeeded));
            //
            try
            {
                Dictionary<string, string> cDic = VideoClipNameHelper.ConfigData.ReadConfig(cp);
                //
                string key = "REPLAYGAINCOEFFICIENTWMP";
                if (cDic.ContainsKey(key))
                {
                    double rgc = double.Parse(cDic[key], System.Globalization.NumberStyles.Number, System.Globalization.CultureInfo.InvariantCulture);
                    VolumeUtils.ReplayGainCoefficient = rgc;
                }
            }
            catch (Exception e)
            {
                MessageBox.Show(string.Format("Error in {0}: {1}", VideoClipNameHelper.ConfigData.ConfigFileName, e.Message), "ConfigData.ReadConfig()", MessageBoxButton.OK, MessageBoxImage.Error);
                System.IO.File.WriteAllLines("errors.txt", new[] { e.Message + Environment.NewLine }, Encoding.UTF8);
                //
                return;
            }
            //

        }
        protected override void OnSourceInitialized(EventArgs e)
        {
            base.OnSourceInitialized(e);
            HwndSource source = PresentationSource.FromVisual(this) as HwndSource;
            source.AddHook(WndProc);
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            //
            try
            {
                win1_SizeChanged(null, null);
                //
                //
                wmp.AllowDrop = false;
                //wmp.VolumeToMaxAsync();
                wmp.Volume = VolumeUtils.DefaultLevel;
                wmp.LoadedBehavior = MediaState.Manual;

                //wmp.BackColor = System.Drawing.Color.DarkBlue;
                //wmp.AutoLoop = false;
                //wmp.AutoPlay = false;
                //wmp.Toolbar = false;
                //wmp.FullscreenEnabled = false;
                //
                //
                wmp.MediaEnded += Wmp_MediaEnded;
                wmp.MediaOpened += SetWindowToPlay;
                wmp.MediaFailed += Wmp_MediaFailed;
                //
                VideoClipNameHelper.CDBHandler.Initialize();
                //
            }
            catch (Exception e1)
            {
                MessageBox.Show(e1.Message + e1.StackTrace, "Window_Loaded", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        private void Wmp_MediaFailed(object sender, ExceptionRoutedEventArgs e)
        {
            VideoClipNameHelper.CLogger.Write(string.Format("HasAudio={0}, HasVideo={1}, [{2}]", wmp.HasAudio, wmp.HasVideo, md.MediaFiles[currentPlaying].OriginalFile));
            buttonNext_Click(null, null);
        }
        //====================================================================================================================
        //private static int WM_QUERYENDSESSION = 0x11;
        private static int WM_ENDSESSION = 0x16;
        private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        {
            if (msg == WM_ENDSESSION)
            {
                VideoClipNameHelper.CLogger.Write("WM_ENDSESSION");
                //
                wmp.GeneralStop();
                SetWindowToStop();
                this.Close();
                //
                handled = true;
                //
            }
            return IntPtr.Zero;
        }

        public void Dispose()
        {
            //if (null != stat)
            {
                //stat.Dispose();
            }
        }

        //====================================================================================================================
        private object playO = new object();
        private void playCurrent()
        {
            lock (playO)
            {
                win1.Title = "";
                progressBar1.Value = progressBar1.Minimum;
                buttonLikeImage.Source = Resources["Like"] as ImageSource;
                //
                if (0 == md.MediaFiles.Count) return;
                //
                win1.Title = System.IO.Path.GetFileName(md.MediaFiles[currentPlaying].OriginalFile);
                string concatShortName = VideoClipData.GetNameWithoutResolution(md.MediaFiles[currentPlaying].ResolvedFile);
                buttonLike.Tag = concatShortName as Object;
                if (VideoClipNameHelper.CDBHandler.IsLiked(concatShortName))
                {
                    buttonLikeImage.Source = Resources["NoLike"] as ImageSource;
                }
                //
                bool gainExist = false;
                double gain;
                if (VideoClipNameHelper.ReplayGain.ReadGain(md.MediaFiles[currentPlaying].ResolvedFile, out gain))
                {
                    gainExist = true;
                    double l = VolumeUtils.CalculateLevelAndReplayGain(gain);
                    //double l = Math.Min(Math.Max(0.0, VolumeUtils.GetDefaultLevel() + gain), 1.0);
                    VolumeUtils.SetMaxLevel(l);
                }
                else
                {
                    VolumeUtils.SetMaxLevel(VolumeUtils.DefaultLevel);
                }
                //
                wmp.Source = new Uri(md.MediaFiles[currentPlaying].ResolvedFile);
                wmp.VolumeToMaxAsync();
                //
                try
                {
                    // czasmi powstaje błąd, od: mfmkvsrcsnk.dll
                    wmp.GeneralPlay(progressBar1);
                }
                catch(Exception e)
                {
                    VideoClipNameHelper.CLogger.Write("wmp.GeneralPlay() Rxception", e);
                    MessageBox.Show(e.Message, "Play", MessageBoxButton.OK);
                    //
                    string pathName = System.Reflection.Assembly.GetExecutingAssembly().Location;
                    System.Diagnostics.Process.Start(pathName);
                    //
                    //Environment.Exit(0);
                    Application.Current.Shutdown();
                    //
                }
                //
                progressBar1.ToolTip = System.IO.Path.GetFileNameWithoutExtension(md.MediaFiles[currentPlaying].OriginalFile) + " / " + (gainExist ? VolumeUtils.GetMaxLevel().ToString() : "?");
                //
                SetButtonImage(buttonPlay, "Stop");
                //
                progressBar1.Value = progressBar1.Minimum;
                //
                Task.Run(() => { return VideoClipNameHelper.CDBHandler.UpdateData(concatShortName, updatenPlayed: true); }).ConfigureAwait(false);
                //
            }
        }

        private object stopO = new object();
        private void stopPlaying()
        {
            lock (stopO)
            {
                win1.Title = "";
                progressBar1.Value = progressBar1.Minimum;
                //
                buttonLike.Tag = null;
                buttonLikeImage.Source = Resources["Like"] as ImageSource;
                //
                SetButtonImage(buttonPlay, "Play");
                //
                progressBar1.ToolTip = "";
                //
                VideoClipNameHelper.ScreenModes.DoEvents();
                wmp.GeneralStop();
                //
                SetWindowToStop();
            }
            //
        }
        //====================================================================================================================
        private void Wmp_MediaEnded(object sender, RoutedEventArgs e)
        {
            currentPlaying++;
            progressBar1.Value = progressBar1.Maximum;
            //
            if (currentPlaying >= md.MediaFiles.Count)
            {
                VideoClipNameHelper.ScreenModes.DoEvents();
                stopPlaying();
                VideoClipNameHelper.ScreenModes.DoEvents();
                //filesToPlay.Clear();
                currentPlaying = 0;
                SetWindowToStop();
                return;
            }
            playCurrent();
        }

        //====================================================================================================================
        private static System.Windows.Threading.DispatcherTimer dtCursor =
            new System.Windows.Threading.DispatcherTimer() { Interval = new TimeSpan(0, 0, 0, 5), IsEnabled = false };
        private bool dtCursorIsSet = false;
        private void win1_PreviewMouseMove(object sender, MouseEventArgs e)
        {
            if (!dtCursor.IsEnabled)
            {
                if (!dtCursorIsSet)
                {
                    dtCursorIsSet = true;
                    dtCursor.Tick += DtCursor_Tick;
                }
                dtCursor.Start();
            }
            //
            if (wmp.IsPlaying())
            {
                if (Cursors.None == this.Cursor)
                {
                    this.Cursor = Cursors.Arrow;
                    dtCursor.Stop(); dtCursor.Start();
                }
            }
            e.Handled = true;
        }

        private void DtCursor_Tick(object sender, EventArgs e)
        {
            if (wmp.IsPlaying())
            {
                this.Cursor = Cursors.None;
            }
            else
            {
                dtCursor.Stop();
                this.Cursor = Cursors.Arrow;
            }
        }

        //====================================================================================================================
        private void SetWindowToPlay(object sender, RoutedEventArgs e)
        {
            if (0 == md.MediaFiles.Count()) return;
            //
            if (isBetweenTrack) return;
            //
            if (this.WindowState != System.Windows.WindowState.Maximized)
            {
                VideoClipNameHelper.ScreenModes.EnterFullScreenMode(this);
                this.Cursor = Cursors.None;
            }
        }

        private void SetWindowToPause()
        {
            if (isBetweenTrack) return;
            //
            if (this.WindowState != System.Windows.WindowState.Normal)
            {
                VideoClipNameHelper.ScreenModes.LeaveFullScreenMode(this);
                this.Cursor = Cursors.Arrow;
            }
        }

        private void SetWindowToStop()
        {
            if (isBetweenTrack) return;
            //
            if (this.WindowState != System.Windows.WindowState.Normal)
            {
                VideoClipNameHelper.ScreenModes.LeaveFullScreenMode(this);
                this.Cursor = Cursors.Arrow;
            }
        }
        //====================================================================================================================
        private void win1_DragOver(object sender, DragEventArgs e)
        {
            e.Effects = DragDropEffects.Copy;
        }

        private void win1_DragEnter(object sender, DragEventArgs e)
        {
            e.Effects = DragDropEffects.Copy;
        }

        private void win1_Drop(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
            {
                //
                e.Effects = DragDropEffects.Copy;
                //
                stopPlaying();
                //filesToPlay.Clear();
                //
                string[] droppedFiles = (string[])e.Data.GetData(DataFormats.FileDrop);
                //
                //filesToPlay = DirectoryCache.GetFilesFromDirectory(droppedFiles[0]);
                md = VideoClipNameHelper.DirectoryCache.GetFilesFromDirectory(droppedFiles[0]);
                //
                //sCfg.Load(droppedFiles[0]);
                if (md.ArgumentIsDirectory)
                {
                    setRandom(VideoClipNameHelper.GeneralConfig.GetValueBool(md.HintData, "Random"));
                }
                else
                {
                    // argument: plik - gramy kolejno, ignorujac hint
                    setRandom(false);
                }
                //
                //
                //
                currentPlaying = 0;
                //
                if (isRandom && md.MediaFiles.Count > 1)
                {
                    Random rnd = new Random();
                    md.MediaFiles = md.MediaFiles.OrderBy(x => rnd.Next()).ToList<VideoClipNameHelper.MediaFile>();
                    currentPlaying = 0;
                }
                //
                //
                if (md.MediaFiles.Count > 0)
                {
                    playCurrent();
                }
                //
                //
                e.Handled = true;
            }
            //
            e.Effects = DragDropEffects.None;
        }
        //====================================================================================================================

    }
}
